package com.studyroom.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.studyroom.entity.Reservation;
import com.studyroom.entity.Seat;
import com.studyroom.mapper.ReservationMapper;
import com.studyroom.mapper.SeatMapper;
import com.studyroom.service.SeatService;
import com.studyroom.dto.SeatDTO;
import com.studyroom.vo.ReservationVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
import java.util.Arrays;

@Slf4j
@Service
public class SeatServiceImpl extends ServiceImpl<SeatMapper, Seat> implements SeatService {
    
    @Autowired
    private SeatMapper seatMapper;
    
    @Autowired
    private ReservationMapper reservationMapper;
    
    @Override
    public List<Seat> getByRoomId(Long roomId) {
        QueryWrapper<Seat> wrapper = new QueryWrapper<>();
        wrapper.eq("room_id", roomId)
              .orderByAsc("seat_number");
        return list(wrapper);
    }

    @Override
    public List<SeatDTO> getAvailableSeats(Integer roomId) {
        LambdaQueryWrapper<Seat> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Seat::getRoomId, roomId)
               .eq(Seat::getStatus, 1)
               .eq(Seat::getIsOccupied, 0)
               .select(Seat::getId, Seat::getSeatNumber, Seat::getIsOccupied);
               
        return seatMapper.selectList(wrapper)
                .stream()
                .map(seat -> {
                    SeatDTO dto = new SeatDTO();
                    dto.setId(seat.getId());
                    dto.setName(seat.getSeatNumber());
                    dto.setIsOccupied(seat.getIsOccupied());
                    return dto;
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<ReservationVO> getReservations(
        Long seatId, 
        LocalDateTime startTime, 
        LocalDateTime endTime
    ) {
        // 默认查询状态为1和2的预约
        return getReservations(seatId, startTime, endTime, Arrays.asList(1, 2));
    }

    @Override
    public List<ReservationVO> getReservations(
        Long seatId, 
        LocalDateTime startTime, 
        LocalDateTime endTime,
        List<Integer> statusList
    ) {
        // 查询指定时间段内的预约，明确指定预约状态
        List<Reservation> reservations = reservationMapper.selectList(
            new LambdaQueryWrapper<Reservation>()
                .eq(Reservation::getSeatId, seatId)
                .in(Reservation::getStatus, statusList)  // 使用传入的状态列表
                .and(w -> w
                    .between(Reservation::getStartTime, startTime, endTime)
                    .or()
                    .between(Reservation::getEndTime, startTime, endTime)
                    .or()
                    .and(v -> v
                        .le(Reservation::getStartTime, startTime)
                        .ge(Reservation::getEndTime, endTime)
                    )
                )
                .orderByAsc(Reservation::getStartTime)
        );

        // 转换为 VO
        return reservations.stream().map(reservation -> {
            ReservationVO vo = new ReservationVO();
            BeanUtils.copyProperties(reservation, vo);
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public boolean updateSeatOccupation(Long seatId, boolean isOccupied) {
        Seat seat = getById(seatId);
        if (seat == null) {
            return false;
        }
        
        seat.setIsOccupied(isOccupied ? 1 : 0);
        return updateById(seat);
    }

    @Override
    public boolean updateSeatStatus(Long seatId, Integer status) {
        // 创建更新对象
        Seat seat = this.getById(seatId);
        if (seat == null) {
            return false;
        }
        
        // 确保使用正确的字段名 - 基于实体类的实际定义
        seat.setStatus(status);
        
        // 执行更新
        return this.updateById(seat);
    }
} 